﻿using CIS.Common.Dtos.ReportDtos;
using CIS.Common.Entitys;
using CIS.Common.Enums;
using CIS.Common.SignalR;
using CIS.Server.Manager.Equipment;
using MediatR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CIS.Server.EQLinker.Equipment
{
    public class EquipmentReportHandler : 
        IRequestHandler<UnitStatusChangeReportDto>,
        IRequestHandler<PortStatusChangeReportDto>
    {
        private readonly IEquipmentManager _equipmentManager;

        public EquipmentReportHandler(IEquipmentManager equipmentManager) 
        {
            this._equipmentManager = equipmentManager;
        }


        public async Task Handle(UnitStatusChangeReportDto request, CancellationToken cancellationToken)
        {
            Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}Received {request.SourceId} {request.EventName}");
            UnitEntity unit = await _equipmentManager.GetUnitBySourceIdAsync(request.SourceId);
            if (unit != null)
            {
                unit.Status = (EquipmentStatus)request.UnitStatus;
                await _equipmentManager.SendUnitStatusChangeReportAsync(request);
            }
        }

        public async Task Handle(PortStatusChangeReportDto request, CancellationToken cancellationToken)
        {
            Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}  Received {request.SourceId} {request.EventName}");
            PortStatusChangeReportDto reportDto = new PortStatusChangeReportDto();
            PortEntity port = await _equipmentManager.GetPortByPortIdAsync(request.PortId);
            if (port != null)
            {
                port.Status = request.PortStatus;
                port.CassetteId = request.CassetteID;
                if(port.Status == PortStatus.InUse)
                {
                    port.CassetteSequenceNo = GetCassetteSequenceNo(port.CassetteSequenceNo);
                    port.LotId = "AN00" + DateTime.Now.Year.ToString() + port.CassetteSequenceNo.ToString();
                }                
                port.JobCountinCassette = request.JobCountInCassette;
                port.CassetteStatus = GetCassetteStatus(port.Status);                
                port.SlotMap = request.SlotMap;
                await _equipmentManager.UpdatePortAsync(port);
                request.CassetteSequenceNo = (short)port.CassetteSequenceNo;
                request.CassetteStatus = port.CassetteStatus;
                request.LotId = port.LotId;
                Dictionary<string, object> message = new Dictionary<string, object>();
                message["EventName"] = "PortStatusChangeReport";
                message["Status"] = request;
                Worker.SendDataToClient(message);
            }
            if (port != null)
            {
                port.Status = (PortStatus)request.PortStatus;
                await _equipmentManager.SendPortStatusChangeReportAsync(request);
            }
        }



        /// <summary>
        /// 获取 Port Cassette Status 状态
        /// </summary>
        /// <param name="portStatus"></param>
        /// <returns></returns>
        private CassetteProcess GetCassetteStatus(PortStatus portStatus)
        {
            CassetteProcess process = 0;
            switch (portStatus)
            {
                case PortStatus.Emty:
                    process = CassetteProcess.NoCassetteExist;
                    break;
                case PortStatus.InUse:
                    process = CassetteProcess.WaitforCSTData;
                    break;
                case PortStatus.LoadReay:
                    process = CassetteProcess.NoCassetteExist;
                    break;
                case PortStatus.UnLoadReady:
                    process = CassetteProcess.ProcessEnd;
                    break;
            }
            return process;
        }

        private int GetCassetteSequenceNo(int cassetteSequenceNo)
        {
            int a = cassetteSequenceNo / 1000;
            int b = a * 1000;
            int c = a * 1000 + 999;
            if (cassetteSequenceNo > b && cassetteSequenceNo < c)
            {
                cassetteSequenceNo++;
            }
            else
            {
                cassetteSequenceNo = a * 1000 + 1;
            }
            return cassetteSequenceNo;
        }
    }
}
